package com.videoaggre.zcl.helper

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.os.Parcelable
import androidx.fragment.app.Fragment
import com.videoaggre.zcl.utils.Logger
import org.koin.android.ext.android.inject
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin
import org.koin.core.logger.Level
import org.koin.core.parameter.parametersOf
import org.koin.dsl.module
import java.io.Serializable
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
import kotlin.reflect.KProperty

/**
 * 依赖注入初始化
 */
fun koinInit(app: Application) {
    val appModule = module {
//        single<HelloRepository> { HelloRepositoryImpl() }
//        factory { (activity: Activity) -> NyTest(activity) }
//        factory { MySimplePresenter(get()) }
//        private val nyTest: NyTest by inject { parametersOf(this) }
    }
    startKoin {
        androidLogger(Level.ERROR)
        androidContext(app)
        modules(appModule)
    }
}

/**
 * 自动创建无参数类
 */
inline fun <reified T : Any> newInstance() = lazy(LazyThreadSafetyMode.NONE) { T::class.java.newInstance() }

/**
 * 给Activity,fragment中的字段自动注入值，其他场景不支持可以自己扩展实现实现得可能不完美可以自己扩展实现
 * 使用方式：
 * private val accountId: Int by InjectBundle()
 */
class InjectBundle<T : Any>(private val defaultValue: (() -> T?)? = null) : ReadOnlyProperty<Any?, T> {
    private var value: Any? = null

    @Suppress("unchecked_cast")
    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        if (value == null) {
            val bundle = when (thisRef) {
                is Activity -> thisRef.intent.extras
                is Fragment -> thisRef.arguments
                else -> throw RuntimeException("该场景不支持请自行扩展实现")
            } ?: Bundle()
            value = (property.returnType.classifier as KClass<*>).java.let {
                when {
                    String::class.java.isAssignableFrom(it) -> bundle.getString(property.name, defaultValue?.invoke() as? String ?: "")
                    Int::class.java.isAssignableFrom(it) -> bundle.getInt(property.name, defaultValue?.invoke() as? Int ?: 0)
                    Boolean::class.java.isAssignableFrom(it) -> bundle.getBoolean(property.name, defaultValue?.invoke() as? Boolean ?: false)
                    Double::class.java.isAssignableFrom(it) -> bundle.getDouble(property.name, defaultValue?.invoke() as? Double ?: 0.0)
                    Long::class.java.isAssignableFrom(it) -> bundle.getLong(property.name, defaultValue?.invoke() as? Long ?: 0)
                    Byte::class.java.isAssignableFrom(it) -> bundle.getByte(property.name, defaultValue?.invoke() as? Byte ?: 0)
                    Char::class.java.isAssignableFrom(it) -> bundle.getChar(property.name, defaultValue?.invoke() as? Char ?: '0')
                    Float::class.java.isAssignableFrom(it) -> bundle.getFloat(property.name, defaultValue?.invoke() as? Float ?: 0.0f)
                    Short::class.java.isAssignableFrom(it) -> bundle.getShort(property.name, defaultValue?.invoke() as? Short ?: 0)
                    Parcelable::class.java.isAssignableFrom(it) -> bundle.getParcelable(property.name) ?: defaultValue?.invoke() ?: throw RuntimeException("Parcelable类型请赋默认值")
                    Serializable::class.java.isAssignableFrom(it) -> bundle.getSerializable(property.name) ?: defaultValue?.invoke() ?: throw RuntimeException("Serializable类型请赋默认值")
                    else -> when {
                        defaultValue != null -> {
                            Logger.e("${it.name}|未找到对应值")
                            defaultValue.invoke()
                        }
                        else -> throw RuntimeException("未支持的注入类，请自己实现")
                    }
                }
            }
        }
        return value as T
    }
}